package trace.plugin.annotation;


import java.lang.reflect.Method;

import easy.trace.Span;
import easy.trace.agent.Tracer;
import easy.trace.agent.support.BaseInterceptor;
import easy.trace.extension.Trace;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

@Aspect
public class TraceInterceptor {
    private static Logger logger = LoggerFactory.getLogger(TraceInterceptor.class);
    private static Tracer tracer;
    private BaseInterceptor interceptor;

    public TraceInterceptor() {
    }

    @Pointcut("execution(public * *(..)) && @annotation(easy.trace.extension.Trace)")
    private void pointcut() {
    }

    @Around("pointcut()")
    public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature joinPointObject = (MethodSignature)pjp.getSignature();
        Method method = joinPointObject.getMethod();
        boolean flag = method.isAnnotationPresent(Trace.class);
        if (this.interceptor == null) {
            ApplicationContext context = new ClassPathXmlApplicationContext("hydra-config.xml");
            tracer = (Tracer)context.getBean(Tracer.class);
            /*this.interceptor = new BaseInterceptor(tracer);*/
            this.interceptor = new BaseInterceptor();
        }

        if (flag) {
            logger.debug("do Annotation");
            String serviceId = pjp.getSignature().getDeclaringTypeName();
            String methodName = pjp.getSignature().getName();
            logger.debug("serviceId:{} methodName:{}", serviceId, methodName);
            Span span = null;

            try {
                try {
                    span = this.interceptor.newSpan(serviceId, methodName);
                } catch (Exception var21) {
                    logger.error(var21.getMessage());
                }

                Object var25 = pjp.proceed();
                return var25;
            } catch (Throwable var22) {
                Throwable e = var22;
                logger.error(var22.getMessage());

                try {
                    this.interceptor.catchException(e);
                } catch (Exception var20) {
                    logger.error(var20.getMessage());
                }
            } finally {
                try {
                    this.interceptor.invokerAfter(span);
                } catch (Exception var19) {
                    logger.error(var19.getMessage());
                }

            }

            logger.debug("finish Annotation");
            logger.debug("end TraceInterceptor");
            return null;
        } else {
            logger.debug("start method");
            return pjp.proceed();
        }
    }
}

